/* 
 * File:   ObjectModel.h
 * Author: Pie
 *
 * Created on April 25, 2011, 4:09 PM
 */

#ifndef SCENE_H
#define	SCENE_H

#include <string>
#include <vector>

#include <assimp.hpp>
#include <aiPostProcess.h>
#include <aiScene.h>

using namespace Assimp;
using namespace std;


struct SceneAnim {
    string _name;
};

struct Vbo {
    float x, y, z;
    float nx, ny, nz;
    float u, v;
};

struct ObjectNode {
    string _name;
    int* _mesh;
    int _num_mesh;
    ObjectNode* _parent;
    ObjectNode** _children;
    int _num_ch;
    aiMatrix4x4 _transform;

    ObjectNode(aiNode* node, ObjectNode* parent=0);
    ~ObjectNode();
    
    void write(ofstream* out);
};

struct ObjectBone {
    string _name;
    aiMatrix4x4 _offset;
    aiVertexWeight* _weights;
    int _num_w;

    ObjectBone(aiBone* bone);
    ~ObjectBone();

    void write(ofstream* out);
};

struct ObjectChannel {
    string _name;
    aiAnimBehaviour _pre;
    aiAnimBehaviour _post;

    aiVectorKey* _pos_keys;
    aiVectorKey* _scale_keys;
    aiQuatKey* _rotate_keys;

    int _num_p;
    int _num_s;
    int _num_r;

    ObjectChannel(aiNodeAnim* chan);
    ~ObjectChannel();
    
    void write(ofstream* out);
};

struct ObjectAnimation {
    string _name;
    int _duration;
    int _tickps;

    ObjectChannel** _chan;

    int _num_chan;

    ObjectAnimation(aiAnimation* anim);
    ~ObjectAnimation();
    
    void write(ofstream* out);
};

struct ObjectFace {
    int _0;
    int _1;
    int _2;
    
    ObjectFace(int _0, int _1, int _2);
    ~ObjectFace();
    void write(ofstream* out);
};

struct ObjectVertex {
    aiVector3D* _pos;
    aiVector3D* _norm;
    aiVector2D* _uv;

    ObjectVertex(aiVector3D* pos, aiVector3D* norm, aiVector3D* uv);
    ~ObjectVertex();

    void to_vbo(Vbo* vbo);
    
    void write(ofstream* out);
};

struct ObjectMesh {
    string _name;
    int _mat;

    ObjectVertex** _vert;
    ObjectFace** _face;
    ObjectBone** _bone;

    int _num_v;
    int _num_f;
    int _num_b;

    ObjectMesh(const aiMesh* mesh);
    ~ObjectMesh();

    void write(ofstream* out);
};

struct ObjectMaterial {
    float _diffuse[4];
    float _specular[4];
    float _ambient[4];
    float _emission[4];
    float _shininess;
    string _texture;
    int   _texture_index;

    ObjectMaterial(const aiMaterial* mtl);
    void write(ofstream* out);
};

struct SceneModel {
    ObjectAnimation** _anim;
    ObjectMesh** _mesh;
    ObjectMaterial** _matl;
    ObjectNode* _node;
    string* _textures;

    int _num_anim;
    int _num_mesh;
    int _num_matl;
    int _num_tex;

    SceneModel(const aiScene* scene);
    ~SceneModel();
    
    void write(ofstream* out);
};

class SceneNode {
private:
    SceneModel* _scene;
    SceneNode* _parent;
    vector<SceneNode*> _children;
    
public:
    SceneNode();
    virtual ~SceneNode();
    
    void load(SceneModel* scene);
    void add_child(SceneNode* child);
    void set_parent(SceneNode* parent);

    void write(const string& file);
};

#endif	/* SCENE_H */

